go-micro v3添加熔断
docker-compose添加熔断服务
version: '3'
services:
# 注册中心集群版本设置
consul1:
image: cap1573/consul
container_name: node1
# 以 server 模式启动
command: agent -server -bootstrap-expect=3 -node=node1 -bind=0.0.0.0 -client=0.0.0.0 -datacenter=dc1
consul2:
image: cap1573/consul
container_name: node2
# 以 server 模式启动
command: agent -server -retry-join=node1 -bootstrap-expect=3 -node=node2 -bind=0.0.0.0 -client=0.0.0.0 -datacenter=dc1
depends_on:
# 依赖consul1启动好之后
- consul1
consul3:
image: cap1573/consul
container_name: node3
# 以 server 模式启动
command: agent -server -retry-join=node1 -bootstrap-expect=3 -node=node3 -bind=0.0.0.0 -client=0.0.0.0 -datacenter=dc1
depends_on:
# 依赖consul1启动好之后
- consul1
# 添加对外暴露的节点 启动控制面板
consul4:
image: consul
container_name: node4
command: agent -retry-join=node1 -node=node4 -bind=0.0.0.0 -client=0.0.0.0 -datacenter=dc1 -ui
ports:
- 8500:8500
depends_on:
- consul2
- consul3
# 添加数据库
paas-mysql:
image: cap1573/mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: 123456
container_name: paas-mysql
# 我们这里换个端口,本地已经有3306了
ports:
- "3308:3306"
# 需要将重要的数据挂盘
volumes:
- ./mysql:/var/lib/mysql
# 添加jaeger 服务
jaeger:
image: cap1573/jaeger
ports:
- "6831:6831/udp"
- "16686:16686"
# 添加熔断看板
hystrix-dasboard:
# 镜像名称
image: cap1573/hystrix-dashboard
ports:
- "9002:9002"
然后重新启动
docker-compose up
看板访问地址:http://127.0.0.1:9002/hystrix
url一定要带上/hystrix
,不然访问不到
base服务添加熔断器服务
go get github.com/afex/hystrix-go/hystrix
package main
import (
"fmt"
"github.com/wujie/base/handler"
base "github.com/wujie/base/proto/base"
"github.com/wujie/common"
"github.com/afex/hystrix-go/hystrix"
"github.com/asim/go-micro/v3/registry"
"github.com/jinzhu/gorm"
"github.com/opentracing/opentracing-go"
"net"
"net/http"
//"github.com/afex/hystrix-go/hystrix"
"github.com/asim/go-micro/plugins/registry/consul/v3"
opentracing2 "github.com/asim/go-micro/plugins/wrapper/trace/opentracing/v3"
"github.com/asim/go-micro/v3"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
func main() {
//需要本地启动,mysql,consul中间件服务
//1.注册中心
//consul := consul.NewRegistry(func(options *registry.Options) {
// options.Addrs = []string{
// consulHost + ":" + strconv.FormatInt(consulPort, 10),
// }
//})
consul := consul.NewRegistry(func(options *registry.Options) {
options.Addrs = []string{
"localhost:8500",
}
})
//2.配置中心,存放经常变动的变量
consulConfig, err := common.GetConsulConfig("localhost", consulPort, "/micro/config")
if err != nil {
//common.Error(err)
fmt.Println(err)
}
fmt.Println(consulConfig)
//3.使用配置中心连接 mysql
// 这里的path是相对于 /micro/config 目录路径
mysqlInfo := common.GetMysqlFromConsul(consulConfig, "mysql")
//初始化数据库
fmt.Println(mysqlInfo)
db, err := gorm.Open("mysql", mysqlInfo.User+":"+mysqlInfo.Pwd+"@("+mysqlInfo.Host+":3308)/"+mysqlInfo.Database+"?charset=utf8&parseTime=True&loc=Local")
if err != nil {
//命令行输出下,方便查看错误
fmt.Println(err)
common.Fatal(err)
fmt.Println("mysql连接失败")
}
fmt.Println("mysql连接成功")
defer db.Close()
//禁止复表
db.SingularTable(true)
//4.添加链路追踪
//t, io, err := common.NewTracer("go.micro.service.base", tracerHost+":"+strconv.Itoa(tracerPort))
t, io, err := common.NewTracer("base", "localhost:6831")
if err != nil {
//common.Error(err)
fmt.Println(err)
}
defer io.Close()
// 设置全局变量
opentracing.SetGlobalTracer(t)
// 5. 添加熔断器,作为客户端需要启用
hystrixStreamHandler := hystrix.NewStreamHandler()
// 启动
hystrixStreamHandler.Start()
//启动监听程序
go func() {
// 需要使用对应的主机ip不用127.0.0.1
//http://192.168.0.112:9092/turbine/turbine.stream
//看板访问地址 http://127.0.0.1:9002/hystrix,url后面一定要带 /hystrix
err = http.ListenAndServe(net.JoinHostPort("0.0.0.0", "9092"), hystrixStreamHandler)
if err != nil {
// 简单处理error
fmt.Println(err)
}
}()
service := micro.NewService(
micro.Name("base-wj"),
micro.Version("latest"),
// 添加注册中心
micro.Registry(consul),
// 添加链路追踪
micro.WrapHandler(opentracing2.NewHandlerWrapper(opentracing.GlobalTracer())),
// 客户端的方式
micro.WrapClient(opentracing2.NewClientWrapper(opentracing.GlobalTracer())),
)
service.Init()
base.RegisterBaseHandler(service.Server(), new(handler.BaseHandler))
// 启动服务
if err := service.Run(); err != nil {
//输出启动失败信息
common.Fatal(err)
}
}
把熔断注册到服务中去,我们还需要单独写一个hystrix
的插件
go get github.com/asim/go-micro/v3/client
plugin/hystrix/hytrix.go
package hystrix
import (
"context"
"fmt"
"github.com/afex/hystrix-go/hystrix"
"github.com/asim/go-micro/v3/client"
)
type clientWrapper struct {
client.Client
}
// Call 熔断逻辑
func (c *clientWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
return hystrix.Do(req.Service()+"."+req.Endpoint(), func() error {
//正常执行
fmt.Println(req.Service() + "." + req.Endpoint())
return c.Client.Call(ctx, req, rsp, opts...)
}, func(e error) error {
//走熔断逻辑,每个服务都不一样
fmt.Println(req.Service() + "." + req.Endpoint() + "的熔断逻辑")
return e
})
}
func NewClientHystrixWrapper() client.Wrapper {
return func(i client.Client) client.Client {
return &clientWrapper{i}
}
}
服务添加代码
service := micro.NewService(
micro.Name("base-wj"),
micro.Version("latest"),
// 添加注册中心
micro.Registry(consul),
// 添加链路追踪
micro.WrapHandler(opentracing2.NewHandlerWrapper(opentracing.GlobalTracer())),
// 客户端的方式
micro.WrapClient(opentracing2.NewClientWrapper(opentracing.GlobalTracer())),
// 只作为客户端的时候起作用
micro.WrapClient(hystrix2.NewClientHystrixWrapper()),
// 添加限流
micro.WrapHandler(ratelimit.NewHandlerWrapper(1000)),
)